#include "StdAfx.h"
#include "Core.h"
#include "CharacterOperations.h"
#include <iostream>
#include <sstream>

using std::string;				using std::cout;				
using std::vector;				using std::endl;
using std::runtime_error;		using std::cerr;
using std::ostringstream;

/* Constructor / Descructor */
Core::Core(string filePath)
{
	file = new CodeFile(filePath);
}

Core::~Core()
{
	delete file;
}	

/* Main Compilation Method */
string Core::Compile()
{
	// Prepare by getting the first character and skipping whitespace
	file->GetNextChar();	
	file->SkipWhite();
	
	Assignment();

	int number = file->Table['B'];

	string textNumber = static_cast<ostringstream*>( &(ostringstream() << number) )->str();

	return textNumber;
}

int Core::Expression()
{
	int value;

	if(IsAddOp(file->Lookahead))
	{
		value = 0;
	}
	else
	{
		value = Term();
	}

	while(IsAddOp(file->Lookahead))
	{
		switch(file->Lookahead)
		{
		case '+':
			file->Match('+');
			value = value + Term();
			break;
		case '-':
			file->Match('-');
			value = value - Term();
			break;
		default:
			throw runtime_error("an addop was not passed to the method correctly");
		}
	}

	return value;
}

int Core::Term()
{
	int value;

	value = Factor();

	while(IsMulOp(file->Lookahead))
	{
		switch(file->Lookahead)
		{
		case '*':
			file->Match('*');
			value = value * Factor();
			break;
		case '/':
			file->Match('/');
			value = value / Factor();
			break;
		}
	}

	return value;
}

int Core::Factor()
{
	int value;

	if(file->Lookahead == '(')
	{
		file->Match('(');
		value = Expression();
		file->Match(')');	
	}
	else if (IsLetter(file->Lookahead))
	{
		char name = file->GetName();
		value = file->Table[name];
	}
	else
	{
		value = file->GetNum();
	}

	return value;	
}

void Core::Assignment()
{
	char name = file->GetName();
	file->Match('=');
	file->Table[name] = Expression();
}